package catan.tiles;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Defines a Tile, for purposes of defining
 * and keeping track of a Board's layout.
 * @author jsilva
 */
public class Tile {
	/**
	 * The number of sides of a hexagon.
	 */
	public static final int HEX_SIDES = 6;
	
	/**
	 * The type of resource this tile produces.
	 */
	private final TileType type;
	
	/**
	 * The number from 2 to 12 that this tile produces resources for.
	 */
	private final int roll_number;
	
	/**
	 * The neighbours surrounding this tile,
	 * starting with the one in the 12 o'clock position (or 1:30)
	 */
	private final List<Tile> neighbours = new ArrayList<Tile>(HEX_SIDES);
	
	/**
	 * Part of an absolute position/index.
	 * Specifies the number of the ring (zero-based) this tile resides in.
	 */
	private final int depth;
	
	/**
	 * Part of an absolute position/index.
	 * Specifies the clockwise position of this tile within its ring, 
	 * zero-based and starting at 12 o'clock (or 1:30).
	 */
	private final int position;
	
	// TODO: Robber?
	
	/**
	 * @return The type of resource this tile produces.
	 */
	public TileType getType() {
		return type;
	}
	
	/**
	 * @return The dice number on which this tile produces its resource.
	 */
	public int getRollNumber() {
		return roll_number;
	}
	
	/**
	 * @return The zero-based number defining 
	 *     what ring this tile belongs to.
	 */
	public int getDepth() {
		return depth;
	}
	
	/**
	 * @return The position of this tile in its ring.
	 */
	public int getPosition() {
		return position;
	}
	
	/**
	 * @param pos The position of the neighbour tile (zero-based,
	 * 		starting from 12 o'clock or 1:30), from 0 to HEX_SIDES.
	 * @param neighbour The neighbour tile to set.
	 */
	public void setNeighbour(int pos, Tile neighbour) {
		if (pos >= neighbours.size() || pos < 0) {
			throw new IllegalArgumentException("Invalid index.");
		} else if (neighbours.get(pos) != null) { 
			throw new IllegalArgumentException("Neighbour already set.");
		}
		neighbours.set(pos, neighbour);		
	}
	
	/**
	 * @return An unmodifiable view of this tile's neighbours.
	 */
	public List<Tile> getNeighbours() {
		return Collections.unmodifiableList(neighbours);
	}
	
	/**
	 * @param type The resource type of the tile.
	 * @param roll_number The dice roll total corresponding to the tile.
	 * @param depth The ring number this tile below to (zero-based).
	 * @param position The position of this tile within its ring (zero-based,
	 * 		starting at 12 o'clock or 1:30).
	 */
	public Tile(TileType type, int roll_number, int depth, int position) {
		this.type = type;
		this.roll_number = roll_number;	
		this.depth = depth;
		this.position = position;		
		for (int i = 0; i < HEX_SIDES; i++) {
			neighbours.add(null);
		}
	}
}
